#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>

#define SEP " "
#define SEP_LEN strlen(SEP)             //不能使用sizeof
#define LINE_SEP "\r\n"
#define LINE_SEP_LIN strlen(LINE_SEP)   //不能使用sizeof

enum{ OK = 0,DEV_ZERO,MOD_ZERO,OP_ERROR};

//定制协议，添加报头
// "x op y" -> "content_len"\r\n"x op y"\r\n
string enLength(const string& text) 
{
    string send_str = to_string(text.size());
    send_str += LINE_SEP;
    send_str += text;
    send_str += LINE_SEP;

    return send_str;
}
//定制协议，去掉报头
// "content_len"\r\n"exitcode result"\r\n -> "exitcode result"
bool deLength(const string& package,string* text)
{
    auto pos = package.find(LINE_SEP);
    if(pos == string::npos)
        return false;

    string text_len_str = package.substr(0,pos);
    int text_len = stoi(text_len_str);
    *text = package.substr(pos+LINE_SEP_LIN,text_len);

    return true;    
}
// 读取一个完整的请求
// "content_len"\r\n"x op y"\r\n
bool recvPackage(int sock,string& inbuffer,string* text)
{

    char buffer[1024];
    while(true)
    {
        ssize_t n = recv(sock,buffer,sizeof(buffer)-1,0);
        if(n > 0)
        {
            buffer[n] = 0;
            inbuffer += buffer;
            // 分析处理
            auto pos = inbuffer.find(LINE_SEP);
            if(pos == string::npos) //一个请求都不完整，继续读取
                continue;
            string text_len_str = inbuffer.substr(0,pos);
            int text_len = stoi(text_len_str);

            // text_len_str.size() + 2*LINE_SEP_LIN +text_len <= inbuffer.size() 证明至少有一个完整的请求 
            int total_len = text_len_str.size() + 2*LINE_SEP_LIN +text_len;
            if(inbuffer.size() < total_len)//一个请求都不完整，继续读取
                continue;
            // cout << "inbuffer处理前: \n" << inbuffer << endl;
            // 至少有一个完整的请求 
            *text = inbuffer.substr(0,total_len);
            inbuffer.erase(0,total_len);

            // cout << "inbuffer处理后: \n" << inbuffer << endl;
            break;
        }
        else return false;
    }
    return true;
}
//由于是阻塞式读取，所以这种方法暂时用不了
// bool recvRequestAll(int sock,vector<string>* out)
// {
//     string line;
//     while(recvRequest(sock,&line))
//         out->push_back(line);
// }

class Request
{
public:
    Request()
        :_x(0),_y(0),_op(0)
    {} 
    Request(int x,int y,char op)
        :_x(x),_y(y),_op(op)
    {} 
    //序列化，通过条件编译可以随意切换，是用自己写的，还是使用工具
    bool serialize(string* out)
    {
#ifdef MYSELF 
        //结构化数据 -> "x op y"
        *out = "";
        string x_str = to_string(_x);
        string y_str = to_string(_y);

        *out = x_str;   
        *out += SEP;
        *out += _op;    
        *out += SEP;
        *out += y_str;  
#else   //使用Json工具
        Json::Value root;
        root["first"] = _x;
        root["second"] = _y;
        root["oper"] = _op;

        Json::FastWriter writer;
        *out = writer.write(root);

#endif
        return true;
    }
    //反序列化
    bool deserialize(const string& in)
    {
        //"x op y" -> 结构化数据
#ifdef MYSELF 
        auto left = in.find(SEP);
        auto right = in.rfind(SEP);

        if(left == string::npos || right == string:: npos || left == right)
            return false;
        if(right- (left + SEP_LEN) != 1) 
            return false;
        string x_str = in.substr(0,left);
        string y_str = in.substr(right+SEP_LEN);
        if(x_str.empty() || y_str.empty())
            return false;

        _x = stoi(x_str);
        _y = stoi(y_str);
        _op = in[left+SEP_LEN];
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in,root);
        _x = root["first"].asInt();
        _y = root["second"].asInt();
        _op = root["oper"].asInt();

#endif
        return true;
    }
public:
    // "x op y"
    int _x;
    int _y;
    char _op;
};

class Response
{
public:
    Response()
        :_exitcode(0),_result(0)
    {}
    Response(const int exitcode,int result)
        :_exitcode(exitcode),_result(result)
    {}
    //自己写
    //序列化
    bool serialize(string* out)
    {
#ifdef MYSELF 
        *out = "";
        string ec_str = to_string(_exitcode);
        string re_str = to_string(_result);

        *out = ec_str;
        *out += SEP;
        *out += re_str;
#else
        Json::Value root;
        root["exitcode"] = _exitcode;
        root["result"] = _result;
        Json::FastWriter writer;
        *out = writer.write(root);

#endif
        return true;
    }
    //反序列化
    bool deserialize(const string& in)
    {
#ifdef MYSELF
        // "exitcode result"
        auto pos = in.find(SEP);
        if(pos == string::npos)
            return false;
        
        string ec_str = in.substr(0,pos);
        string re_str = in.substr(pos + SEP_LEN);
        if(ec_str.empty() || re_str.empty())
            return false;
        
        _exitcode = stoi(ec_str);
        _result = stoi(re_str);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in,root);
        _exitcode = root["exitcode"].asInt();
        _result = root["result"].asInt();


#endif
        return true;
    }
public:
    int _exitcode;   // 0：表示计算成功 !0：表示计算失败，具体的是多少会有一个标准
    int _result;     //计算结果
};

